package org.zfm.car.service.impl;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.transaction.annotation.Transactional;
import org.zfm.base.config.MyResultMapper;
import org.zfm.car.doc.CarDoc;
import org.zfm.car.domain.Car;
import org.zfm.car.domain.CarDetail;
import org.zfm.car.domain.CarOnlineAuditLog;
import org.zfm.car.domain.CarType;
import org.zfm.car.mapper.CarDetailMapper;
import org.zfm.car.mapper.CarMapper;
import org.zfm.car.mapper.CarOnlineAuditLogMapper;
import org.zfm.car.mapper.CarResourcesMapper;
import org.zfm.car.query.CarSearchQuery;
import org.zfm.car.service.ICarService;
import org.zfm.base.service.impl.BaseServiceImpl;
import org.springframework.stereotype.Service;
import org.zfm.org.domain.Employee;
import org.zfm.org.domain.Shop;
import org.zfm.org.mapper.EmployeeMapper;
import org.zfm.org.service.IBaiduAiService;
import org.zfm.repostory.CarRepository;
import org.zfm.util.data.AjaxResult;
import org.zfm.util.data.PageData;
import org.zfm.util.utils.ThreadPoolUtil;
import org.zfm.util.utils.VelocityUtils;

import java.io.File;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zara
 * @since 2022-11-03
 */
@Service
public class CarServiceImpl extends BaseServiceImpl<Car> implements ICarService {
    @Autowired
    private CarDetailMapper carDetailMapper;

    @Autowired
    private CarMapper carMapper;
    @Autowired
    private CarResourcesMapper carResourcesMapper;
    @Autowired
    private EmployeeMapper employeeMapper;
    @Autowired
    private IBaiduAiService baiduAiService;
    @Autowired
    private MyResultMapper myResultMapper;

    @Autowired
    private CarRepository carRepository;

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    @Autowired
    private CarOnlineAuditLogMapper carOnlineAuditLogMapper;

    @Value(value = "${model.path}")
    private String modelPath;

    @Value(value = "${object.file_path}")
    private String targetPath;

    @Override
    @Transactional
    public void delete(Serializable id) {
        super.delete(id);
        carDetailMapper.deleteByCarId(id);
        carResourcesMapper.deleteByCarId(id);
    }

    @Override
    @Transactional
    public void insert(Car car) {
        //设置创建时间
        car.setCreatetime(new Date());
        //设置销售员--获取当前登录用户
        Employee employee = employeeMapper.selectById(1l);
        car.setSeller(employee);
        //设置店铺id--根据当前登录用户获取店铺
        car.setShopId(employee.getShopId());
        //设置审核状态--未审核时，默认审核状态为待审核
        car.setAuditstate(0);
        //设置售卖状态---默认是下架
        car.setState(0);
        //新增
        super.insert(car);
        //获取车辆详情
        CarDetail carDetail = car.getCarDetail();
        carDetail.setCartitle(car.getTitle());
        //设置车辆详情表车辆id
        carDetail.setCarId(car.getId());
        carDetailMapper.insert(carDetail);
        //自动审核
        ThreadPoolUtil.INSTANCE.getThreadPool().submit(new Runnable() {
            @Override
            public void run() {
                audit(car);
            }
        });
    }
    private void audit(Car car){
        //调用百度AI自动审核
        AjaxResult audit =
                baiduAiService.audit(car.getTitle() + car.getCarDetail().getInfo(), car.getCover(), null);
        //添加审核日志
        CarOnlineAuditLog log = new CarOnlineAuditLog();
        log.setAudit_time(new Date());
        log.setCarId(car.getId());
        if(audit.getSuccess()){
            log.setState(1);//审核通过
        }else {
            log.setState(2);//审核驳回
            log.setNote("审核未通过，原因："+audit.getMessage());
        }
        carOnlineAuditLogMapper.insert(log);
        //更改审核状态
        car.setState(log.getState());
        super.insert(car);
    }

    /**
     * 上架
     * @param ids
     */
    @Override
    @Transactional
    public int onSale(List<Long> ids) {
        //判空
        if(ids==null||ids.size()<1){
            throw new RuntimeException("请先选择要上架的数据！！！！！！！！！！");
        }
        // 1 修改ids中所有审核通过的数据的状态为上架 并返回修改行数
        int rows = carMapper.onSale(ids);
        // 2 将上架的数据 添加到 ES
        //先查询出刚上架的数据
        List<Car> list = carMapper.selectByIds(ids);
        List<CarDoc> carDocList = new ArrayList<>();
        List<Long> carIds = new ArrayList<>();
        list.forEach(car -> {
            //创建文档对象
            CarDoc carDoc = new CarDoc();
            //复制car中的信息到文档对象
            BeanUtils.copyProperties(car,carDoc);
            //获取车辆详情信息
            CarDetail carDetail = car.getCarDetail();
            carDoc.setCarInfo(carDetail.getInfo());
            //获取店铺信息--店铺id 店铺名字 店铺地址
            Shop shop = car.getShop();
            carDoc.setShopId(shop.getId());
            carDoc.setShopName(shop.getName());
            carDoc.setShopAdress(shop.getAddress());
            //获取车辆类型--类型id 类型名字
            CarType type = car.getType();
            carDoc.setTypeId(type.getId());
            carDoc.setTypeName(type.getName());
            carDocList.add(carDoc);
            carIds.add(car.getId());
        });
        carRepository.saveAll(carDocList);
        // 3 添加上架日志
        addAuditLog(carIds,1);
        // 生成静态页面
        ThreadPoolUtil.INSTANCE.getThreadPool().submit(new Runnable() {
            @Override
            public void run() {
                carDocList.forEach(carDoc -> {
                    VelocityUtils.staticByTemplate(carDoc,modelPath,
                            targetPath+"\\"+carDoc.getId()+".html");
                });
            }
        });
        return rows;
    }

    /**
     * 下架
     * @param ids
     */
    @Override
    @Transactional
    public int offSale(List<Long> ids) {
        if(ids==null||ids.size()<1){
            throw new RuntimeException("请先选择要下架的内容！");
        }
        // 1 修改ids中数据的状态为下架 并修改返回行数
        int rows = carMapper.offSale(ids);
        // 2 将刚下架的数据从ES中删掉
        ArrayList<CarDoc> carDocs = new ArrayList<>();
        ids.forEach(id->{
            CarDoc carDoc = new CarDoc();
            carDoc.setId(id);
            carDocs.add(carDoc);
            // 删除
            ThreadPoolUtil.INSTANCE.getThreadPool().submit(new Runnable() {
                @Override
                public void run() {
                    File file = new File(targetPath + "\\" + id + ".html");
                    if(file.exists())
                        file.delete();
                }
            });
        });
        //删除es中的数据
        carRepository.deleteAll(carDocs);
        // 3 添加下架日志
        addAuditLog(ids,0);

        return rows;
    }

    /**
     * 分页查询
     * @param carSearchQuery
     * @return
     */
    @Override
    public PageData<CarDoc> list(CarSearchQuery carSearchQuery) {
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        //创建查询条件
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //添加关键字模糊查询
        String keyword = carSearchQuery.getKeyword();
        if(StringUtils.isNotBlank(keyword)){
            boolQueryBuilder.must()
                    .add(QueryBuilders.multiMatchQuery(keyword,
                            "shopName","typeName","carInfo","title"));
        }
        //类型匹配
        Long typeId = carSearchQuery.getTypeId();
        if(Objects.nonNull(typeId)){
            boolQueryBuilder.filter()
                    .add(QueryBuilders.termQuery("typeId", typeId));
        }
        //添加筛选
        Integer rushsale = carSearchQuery.getRushsale();
        Integer quasinewcar = carSearchQuery.getQuasinewcar();
        Integer transitivecountry = carSearchQuery.getTransitivecountry();;
        Integer costeffective = carSearchQuery.getCosteffective();
        if(Objects.nonNull(rushsale)){
            boolQueryBuilder.filter().add(QueryBuilders.termQuery("rushsale",rushsale));
        }else if(Objects.nonNull(quasinewcar)){
            boolQueryBuilder.filter().add(QueryBuilders.termQuery("quasinewcar",quasinewcar));
        }else if(Objects.nonNull(transitivecountry)){
            boolQueryBuilder.filter()
                    .add(QueryBuilders.termQuery("transitivecountry",transitivecountry));
        }else if(Objects.nonNull(costeffective)){
            boolQueryBuilder.filter()
                    .add(QueryBuilders.termQuery("costeffective",costeffective));
        }

        //车龄
        Long carAge = carSearchQuery.getCarAge();
        Long carAgeType = carSearchQuery.getCarAgeType();
        if(Objects.nonNull(carAge)&&Objects.nonNull(carAgeType)){
            carAge=0-carAge;
            Date date = DateUtils.addYears(new Date(), Math.toIntExact(carAge));
            if(carAgeType==0){//以内
                boolQueryBuilder.filter()
                        .add(QueryBuilders.rangeQuery("reigstertime").gte(date));
            }else if(carAgeType==1){ //以外
                boolQueryBuilder.filter()
                        .add(QueryBuilders.rangeQuery("reigstertime").lte(date));
            }
        }

        //价格
        BigDecimal maxPrice = carSearchQuery.getMaxPrice();
        BigDecimal minPrice = carSearchQuery.getMinPrice();
        if(Objects.nonNull(maxPrice)){
            boolQueryBuilder.filter()
                    .add(QueryBuilders.rangeQuery("saleprice").lte(maxPrice));
        }
        if(Objects.nonNull(minPrice)){
            boolQueryBuilder.filter()
                    .add(QueryBuilders.rangeQuery("saleprice").gte(minPrice));
        }
        //将查询条件添加到builder中
        builder.withQuery(boolQueryBuilder);
        //分页
        /**
         * PageRequest.of(int page,int size)
         * page 当前页号 从0开始
         * size 每页条数
         */
        builder.withPageable(PageRequest.of((carSearchQuery.getCurrentPage()-1),carSearchQuery.getPageSize()));
        //排序
        String sortField = carSearchQuery.getSortField();
        String sortType = carSearchQuery.getSortType();
        sortType = sortType==null?"DESC":"ASC";
        if(Objects.nonNull(sortField)&&Objects.nonNull(sortType)){
            if("costprice".equals(sortField)){
                if(sortType.equals("ASC")){
                    builder.withSort(SortBuilders.fieldSort("costprice").order(SortOrder.ASC));
                }else if(sortType.equals("DESC")){
                    builder.withSort(SortBuilders.fieldSort("costprice").order(SortOrder.DESC));
                }
            }else if("reigstertime".equals(sortField)){
                if(sortType.equals("ASC")){
                    builder.withSort(SortBuilders.fieldSort("reigstertime").order(SortOrder.ASC));
                }else if(sortType.equals("DESC")){
                    builder.withSort(SortBuilders.fieldSort("reigstertime").order(SortOrder.DESC));
                }
            }else if("mileage".equals(sortField)){
                if(sortType.equals("ASC")){
                    builder.withSort(SortBuilders.fieldSort("mileage").order(SortOrder.ASC));
                }else if(sortType.equals("DESC")){
                    builder.withSort(SortBuilders.fieldSort("mileage").order(SortOrder.DESC));
                }
            }else if("onsaletime".equals(sortField)){
                if(sortType.equals("ASC")){
                    builder.withSort(SortBuilders.fieldSort("onsaletime").order(SortOrder.ASC));
                }else if(sortType.equals("DESC")){
                    builder.withSort(SortBuilders.fieldSort("onsaletime").order(SortOrder.DESC));
                }
            }
        }
        //准备高亮显示器
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.fields().add(new HighlightBuilder.Field("title"));
        highlightBuilder.fields().add(new HighlightBuilder.Field("shopName"));
        highlightBuilder.fields().add(new HighlightBuilder.Field("carInfo"));
        highlightBuilder.fields().add(new HighlightBuilder.Field("typeName"));
        highlightBuilder.preTags("<em style='color:red;'>");
        highlightBuilder.postTags("</em>");
        builder.withHighlightBuilder(highlightBuilder);
        //carRepository不支持高亮显示
        // 5 调search方法到es中查询,封装PageList对象
        Page<CarDoc> search = elasticsearchTemplate.queryForPage(builder.build(),
                CarDoc.class,myResultMapper);
        //Page<CarDoc> search = carRepository.search(builder.build());
        return new PageData<CarDoc>(search.getTotalElements(),search.getContent());
    }

    private void addAuditLog(List<Long> ids, int state) {
        //获取当前用户
        Employee employee = employeeMapper.selectById(1l);
        String info = state==1 ? "上架":"下架";
        ArrayList<CarOnlineAuditLog> logs = new ArrayList<>();
        ids.forEach(id->{
            CarOnlineAuditLog log = new CarOnlineAuditLog();
            log.setState(state);
            log.setAudit_time(new Date());
            log.setCarId(id);
            log.setNote(info);
            log.setAudit_id(employee.getId());
            logs.add(log);
        });
        carOnlineAuditLogMapper.batchInsert(logs);
    }
}
